package org.dromara.common.websocket.config;

import cn.hutool.core.util.StrUtil;
import org.dromara.common.websocket.config.properties.WebSocketProperties;
import org.dromara.common.websocket.handler.PlusWebSocketHandler;
import org.dromara.common.websocket.interceptor.PlusWebSocketInterceptor;
import org.dromara.common.websocket.listener.WebSocketTopicListener;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.server.HandshakeInterceptor;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：WebSocket 配置
 */
@AutoConfiguration
// 当配置属性websocket.enabled设置为true时，条件性地启用WebSocket配置
@ConditionalOnProperty(value = "websocket.enabled", havingValue = "true")
// 启用WebSocketProperties类的配置属性
@EnableConfigurationProperties(WebSocketProperties.class)
// 启用WebSocket支持
@EnableWebSocket
public class WebSocketConfig {

    /**
     * 配置WebSocket
     *
     * @param handshakeInterceptor WebSocket握手拦截器，用于处理握手请求
     * @param webSocketHandler WebSocket处理器，用于处理WebSocket请求
     * @param webSocketProperties WebSocket配置属性，包含WebSocket路径和允许的跨域来源等信息
     * @return 返回配置好的WebSocketConfigurer实例
     *
     * 该方法主要用于配置WebSocket的相关属性并返回一个WebSocketConfigurer对象，
     * 包括设置WebSocket的路径、握手拦截器、处理器以及允许的跨域来源
     */
    @Bean
    public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor handshakeInterceptor,
                                                   WebSocketHandler webSocketHandler, WebSocketProperties webSocketProperties) {
        // 如果WebSocket的路径为空，则设置默认路径为 "/websocket"
        if (StrUtil.isBlank(webSocketProperties.getPath())) {
            webSocketProperties.setPath("/websocket");
        }

        // 如果允许跨域访问的地址为空，则设置为 "*"，表示允许所有来源的跨域请求
        if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) {
            webSocketProperties.setAllowedOrigins("*");
        }

        // 返回一个WebSocketConfigurer对象，用于配置WebSocket
        return registry -> registry
            // 添加WebSocket处理程序和拦截器到指定路径，设置允许的跨域来源
            .addHandler(webSocketHandler, webSocketProperties.getPath())
            // 添加握手拦截器，用于处理WebSocket握手请求
            .addInterceptors(handshakeInterceptor)
            // 设置允许的源，提高跨域访问安全性
            .setAllowedOrigins(webSocketProperties.getAllowedOrigins());
    }

    /**
     * 配置握手拦截器
     *
     * @return PlusWebSocketInterceptor实例
     */
    @Bean
    public HandshakeInterceptor handshakeInterceptor() {
        return new PlusWebSocketInterceptor();
    }

    /**
     * 通过Spring的@Bean注解，将WebSocketHandler的实例注册为一个Bean
     * 这样Spring容器可以管理这个WebSocket处理器的生命周期，并且在需要时自动注入
     */
    @Bean
    public WebSocketHandler webSocketHandler() {
        return new PlusWebSocketHandler();
    }

    /**
     * 定义一个WebSocketTopicListener的Bean
     * 该Bean负责处理WebSocket话题的监听逻辑
     */
    @Bean
    public WebSocketTopicListener topicListener() {
        return new WebSocketTopicListener();
    }
}
